home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dme / command.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  20KB  |  787 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  * COMMAND.C
  9.  *
  10.  * )c             single character (typing)
  11.  * 'c                single character (typing)
  12.  * `string'          string of characters w/ embedded `' allowed!
  13.  * (string)        same thing w/ embedded () allowed!
  14.  * \c             override
  15.  *
  16.  * name arg arg      command name. The arguments are interpreted as strings
  17.  *             for the command.
  18.  *
  19.  * $scanf         macro insert scanf'd variable
  20.  * $filename         macro insert current file name
  21.  *
  22.  * Any string arguments not part of a command are considered to be typed
  23.  * text.
  24.  */
  25.  
  26. #include "defs.h"
  27.  
  28. Prototype void init_command (void);
  29. Prototype int do_command (char *);
  30. Prototype void do_null (void);
  31. Prototype void do_source (void);
  32. Prototype void do_quit (void);
  33. Prototype void do_execute (void);
  34. Prototype void do_repeat (void);
  35. Prototype char *breakout (char **, char *, char **);
  36.  
  37.  
  38. typedef struct Process PROC;
  39.  
  40. #define CF_COK    1   /*    Can be executed while in command line mode    */
  41. #define CF_PAR    2   /*    ESCIMM special flag.. save rest of command line */
  42.             /*    so it can be executed after user entry        */
  43.  
  44. #define CF_ICO    4   /*    OK to execute if iconified, else uniconify first*/
  45.  
  46. #define BTOCP(val, type)    ((type)((long)val << 2))
  47.  
  48. typedef void (*FPTR) ARGS((long));
  49.  
  50. typedef struct {
  51.     const char *name;     /* command name       */
  52.     ubyte args;
  53.     ubyte flags;
  54.     void (*func) ARGS((long));    /* function          */
  55. } COMM;
  56.  
  57. /*============================================================================*/
  58.  
  59. /*
  60.  *  WLEFT/WRIGHT will check command line mode themselves, and thus can
  61.  *  be marked flags=1 even though they can change the line number.
  62.  *
  63.  *  No more than 255 commands may exist unless you change the type of hindex[]
  64.  *
  65.  *  Command names MUST be sorted by their first character
  66.  */
  67.  
  68. static unsigned char hindex[26];    /*    alpha hash into table    */
  69.  
  70.     /*      args flags    */
  71.  
  72. static const COMM Comm[] = {
  73. #ifndef NO_DO2
  74.     "addpath",       1, CF_COK, (FPTR)do_addpath,
  75. #endif
  76.     "append",        1, CF_COK, (FPTR)do_append,
  77.     "arpinsfile",    0,      0, (FPTR)do_arpinsfile,
  78.     "arpload",       0,      0, (FPTR)do_arpload,
  79.     "arpsave",       0,      0, (FPTR)do_arpsave,
  80.     "aslfont",       0,      0, (FPTR)do_aslfont,
  81.     "aslinsfile",    0,      0, (FPTR)do_aslinsfile,
  82.     "aslload",       0,      0, (FPTR)do_aslload,
  83.     "aslsave",       0,      0, (FPTR)do_aslsave,
  84.     "back",          0, CF_COK, (FPTR)do_bs,
  85.     "backtab",       0, CF_COK, (FPTR)do_backtab,
  86.     "bappend",       1, CF_COK, (FPTR)do_bappend,
  87.     "bcopy",         0,      0, (FPTR)do_bcopy,
  88.     "bdelete",       0,      0, (FPTR)do_bdelete,
  89.     "bgpen",         1,      0, (FPTR)do_bgpen,
  90.     "block",         0,      0, (FPTR)do_block,    /* checks com name for mode */
  91.     "bmove",         0,      0, (FPTR)do_bmove,
  92.     "bottom",        0,      0, (FPTR)do_bottom,
  93.     "bs",            0, CF_COK, (FPTR)do_bs,
  94.     "bsave",         1, CF_COK, (FPTR)do_bsave,
  95.     "bsource",       0,      0, (FPTR)do_bsource,
  96.     "cd",            1, CF_COK, (FPTR)do_cd,
  97.     "chfilename",    1,      0, (FPTR)do_chfilename,
  98.     "col",           1, CF_COK, (FPTR)do_col,
  99. #ifndef NO_DO_CTAGS
  100.     "ctags",         0, CF_ICO, (FPTR)do_ctags,
  101. #endif
  102.     "del",           0, CF_COK, (FPTR)do_del,
  103.     "deline",        0,      0, (FPTR)do_deline,
  104.     "down",          0,      0, (FPTR)do_down,
  105.     "downadd",       0,      0, (FPTR)do_downadd,
  106.     "esc",           0, CF_COK, (FPTR)do_esc,
  107.     "escimm",        1, CF_PAR, (FPTR)do_esc,
  108.     "execute",       1, CF_ICO, (FPTR)do_execute,
  109.     "fgpen",         1,      0, (FPTR)do_fgpen,
  110.     "find",          1,      0, (FPTR)do_find,     /* checks com name for mode */
  111.     "findmatch",     0, CF_COK, (FPTR)do_findmatch,
  112.     "findr",         2,      0, (FPTR)do_findr,    /* checks com name for mode */
  113.     "findstr",       1, CF_COK, (FPTR)do_findstr,  /* checks com name for mode */
  114.     "first",         0, CF_COK, (FPTR)do_firstcolumn,
  115.     "firstnb",       0, CF_COK, (FPTR)do_firstnb,
  116.     "goto",          1,      0, (FPTR)do_goto,
  117.     "hgpen",         1,      0, (FPTR)do_hgpen,
  118.     "iconify",       0, CF_ICO, (FPTR)do_iconify,
  119.     "iconsave",      1, CF_COK, (FPTR)do_iconsave,
  120.     "if",            2, CF_COK, (FPTR)do_if,
  121.     "ifelse",        3, CF_COK, (FPTR)do_if,
  122.     "ignorecase",    1, CF_COK, (FPTR)do_ignorecase,
  123.     "insertmode",    1, CF_COK, (FPTR)do_insertmode,
  124.     "insfile",       1,      0, (FPTR)do_edit,
  125.     "insline",       0,      0, (FPTR)do_insline,
  126.     "join",          0,      0, (FPTR)do_join,
  127.     "justify",       1,      0, (FPTR)do_justify,
  128.     "last",          0, CF_COK, (FPTR)do_lastcolumn,
  129.     "left",          0, CF_COK, (FPTR)do_left,
  130.     /*
  131.     "lrow",          1, CF_COK, (FPTR)do_lrow,
  132.     */
  133.     "map",           2, CF_COK, (FPTR)do_map,
  134.     "margin",        1, CF_COK, (FPTR)do_margin,
  135.     "menuon",        0,      0, (FPTR)do_menuon,
  136.     "menuoff",       0,      0, (FPTR)do_menuoff,
  137.     "menuadd",       3,      0, (FPTR)do_menuadd,
  138.     "menudel",       2,      0, (FPTR)do_menudel,
  139.     "menudelhdr",    1,      0, (FPTR)do_menudelhdr,
  140.     "menuclear",     0,      0, (FPTR)do_menuclear,
  141.     "modified",      1,      0, (FPTR)do_modified,
  142.     "newfile",       1,      0, (FPTR)do_edit,     /* checks com name for mode */
  143.     "newwindow",     0, CF_ICO, (FPTR)do_newwindow,
  144.     "next",          0,      0, (FPTR)do_find,
  145.     "nextr",         0,      0, (FPTR)do_findr,
  146.     "null",          0, CF_COK, (FPTR)do_null,
  147.     "openwindow",    1, CF_ICO, (FPTR)do_openwindow,
  148.     "pagedown",      0,      0, (FPTR)do_page,
  149.     "pageset",       1,      0, (FPTR)do_page,
  150.     "pageup",        0,      0, (FPTR)do_page,
  151.     "ping",          1, CF_ICO, (FPTR)do_ping,
  152.     "pong",          1,      0, (FPTR)do_pong,
  153.     "prev",          0,      0, (FPTR)do_find,
  154.     "prevr",         0,      0, (FPTR)do_findr,
  155.     "popmark",       0,      0, (FPTR)do_popmark,
  156.     "purgemark",     0,      0, (FPTR)do_purgemark,
  157.     "pushmark",      0,      0, (FPTR)do_pushmark,
  158.     "quit",          0, CF_ICO, (FPTR)do_quit,
  159.     "recall",        0, CF_COK, (FPTR)do_recall,
  160. #ifndef NO_DO_REFS
  161.     "ref",           0,      0, (FPTR)do_refs,
  162. #endif
  163.     "reformat",      0,      0, (FPTR)do_reformat,
  164.     "remeol",        0, CF_COK, (FPTR)do_remeol,
  165. #ifndef NO_DO2
  166.     "rempath",       1, CF_COK, (FPTR)do_rempath,
  167. #endif
  168.     "repeat",        2, CF_ICO|CF_COK, (FPTR)do_repeat,
  169.     "repstr",        1, CF_COK, (FPTR)do_findstr,
  170.     "resettoggle",   1, CF_COK, (FPTR)do_toggle,
  171.     "resize",        2,      0, (FPTR)do_resize,
  172.     "return",        0, CF_COK, (FPTR)do_return,   /* special meaning in command line mode */
  173.     "right",         0, CF_COK, (FPTR)do_right,
  174. #if AREXX
  175.     "rx",            1,      0, (FPTR)do_rx,       /* explicit ARexx macro invocation      */
  176.     "rx1",           2,      0, (FPTR)do_rx1,      /* explicit, with 1 arg  to ARexx macro */
  177.     "rx2",           3,      0, (FPTR)do_rx2,      /* explicit, with 2 args to ARexx macro */
  178. #endif
  179.     "saveas",        1, CF_ICO|CF_COK, (FPTR)do_saveas,
  180.     "saveconfig",    0, CF_ICO|CF_COK, (FPTR)do_saveconfig,
  181.     "savemap",       1, CF_ICO|CF_COK, (FPTR)do_savemap,  /* checks com name for mode */
  182.     "saveold",       0, CF_ICO|CF_COK, (FPTR)do_save,
  183.     "savesmap",      1, CF_ICO|CF_COK, (FPTR)do_savemap,
  184.     "savetabs",      1, CF_ICO|CF_COK, (FPTR)do_savetabs,
  185.     "scanf",         1, CF_COK, (FPTR)do_scanf,
  186.     "screenbottom",  0,      0, (FPTR)do_screenbottom,
  187.     "screentop",     0,      0, (FPTR)do_screentop,
  188.     "scrollup",      0,      0, (FPTR)do_scrollup,
  189.     "scrolldown",    0,      0, (FPTR)do_scrolldown,
  190.     "set",           2, CF_ICO|CF_COK, (FPTR)do_set,
  191.     "setenv",        2, CF_ICO|CF_COK, (FPTR)do_setenv,
  192.     "setfont",       2,      0, (FPTR)do_setfont,
  193.     "setparcol",     1, CF_COK, (FPTR)do_setparcol,
  194.     "settoggle",     1, CF_COK, (FPTR)do_toggle,
  195.     "source",        1, CF_COK, (FPTR)do_source,
  196.     "split",         0,      0, (FPTR)do_split,
  197.     "swapmark",      0,      0, (FPTR)do_swapmark,
  198.     "tab",           0, CF_COK, (FPTR)do_tab,
  199.     "tabstop",       1, CF_COK, (FPTR)do_tabstop,
  200.     "title",         1,      0, (FPTR)do_title,
  201.     "tlate",         1, CF_COK, (FPTR)do_tlate,
  202.     "toggle",        1, CF_COK, (FPTR)do_toggle,
  203.     "tomouse",       0,      0, (FPTR)do_tomouse,
  204.     "top",           0,      0, (FPTR)do_top,
  205.     "tpen",          1,      0, (FPTR)do_tpen,
  206.     "unblock",       0,      0, (FPTR)do_block,
  207.     "undeline",      0,      0, (FPTR)do_undeline,
  208.     "undo",          0,      0, (FPTR)do_undo,
  209.     "unjustify",     0,      0, (FPTR)do_unjustify,
  210.     "unmap",         1, CF_ICO|CF_COK, (FPTR)do_unmap,
  211.     /*
  212.     "urow",          1, CF_COK, (FPTR)do_urow,
  213.     */
  214.     "unset",         1, CF_ICO|CF_COK, (FPTR)do_unset,
  215.     "unsetenv",      1, CF_ICO|CF_COK, (FPTR)do_unsetenv,
  216.     "up",            0,      0, (FPTR)do_up,
  217.     "while",         2, CF_ICO|CF_COK, (FPTR)do_if,
  218.     "window",        1,      0, (FPTR)do_window,
  219.     "wleft",         0, CF_COK, (FPTR)do_wleft,
  220.     "wordwrap",      1, CF_COK, (FPTR)do_wordwrap,
  221.     "wright",        0, CF_COK, (FPTR)do_wright,
  222.     NULL, 0, 0, NULL
  223. };
  224.  
  225. void
  226. init_command()
  227. {
  228.     short hi;
  229.     COMM *comm;
  230.  
  231.     hi = sizeof(Comm)/sizeof(Comm[0]) - 2;
  232.     comm = Comm + hi;
  233.  
  234.     while (hi >= 0) {
  235.     hindex[comm->name[0] - 'a'] = hi;
  236.     --hi;
  237.     --comm;
  238.     }
  239. }
  240.  
  241. #define MAXIA    5
  242.  
  243. do_command(str)
  244. char *str;
  245. {
  246.     char *arg;
  247.     char *aux1, *aux2;
  248.     char *repstr[MAXIA];
  249.     char quoted;
  250.     short repi = 0;
  251.     short i, j;
  252.     static int level;
  253.  
  254.     if (++level > 20) {
  255.     title("Recursion Too Deep!");
  256.     --level;
  257. #if AREXX
  258.     foundcmd = 1;    /* to prevent us from trying an ARexx macro */
  259. #endif
  260.     return(0);
  261.     }
  262.     while (arg = breakout(&str, "ed, &aux1)) {
  263.     if (quoted) {
  264.         if (Ep->iconmode)
  265.         uniconify();
  266.         text_write(arg);
  267. #if AREXX                /* MMW 1.45 */
  268.         foundcmd = 1;        /* MMW 1.45 */
  269. #endif                    /* MMW 1.45 */
  270.         goto loop;
  271.     }
  272.     for (i = 0; arg[i]; ++i) {
  273.         if (arg[i] >= 'A' && arg[i] <= 'Z')
  274.         arg[i] += 'a' - 'A';
  275.     }
  276.  
  277.     if (arg[0] >= 'a' && arg[0] <= 'z') {
  278.         COMM *comm = &Comm[hindex[arg[0]-'a']];
  279.         for (; comm->name && comm->name[0] == arg[0]; ++comm) {
  280.         if (strcmp(arg, comm->name) == 0) {
  281. #if AREXX
  282.             foundcmd = 1;
  283. #endif
  284.             av[0] = (ubyte *)comm->name;
  285.             for (j = 1; j <= comm->args; ++j) {
  286.             av[j] = (ubyte *)breakout(&str, "ed, &aux2);
  287.             if (aux2) {
  288.                 if (repi == MAXIA) {
  289.                 free(aux2);
  290.                 title("Command too complex");
  291.                 goto fail;
  292.                 } else {
  293.                 repstr[repi++] = aux2;
  294.                 }
  295.             }
  296.             if (!av[j]) {
  297.                 title("Bad argument");
  298.                 goto fail;
  299.             }
  300.             }
  301.             av[j] = NULL;   /* end of arglist */
  302.             if ((comm->flags & CF_COK) || !Comlinemode) {
  303.             if (comm->flags & CF_PAR) {
  304.                 if (Partial)
  305.                 free(Partial);
  306.                 Partial = (char *)malloc(strlen(str)+1);
  307.                 strcpy(Partial, str);
  308.                 str += strlen(str);     /*    skip string */
  309.             }
  310.             if (Ep->iconmode && !(comm->flags & CF_ICO))
  311.                 uniconify();
  312.             (*comm->func)(-1);
  313.             }
  314.             if (Abortcommand)
  315.             goto fail;
  316.             goto loop;
  317.         }
  318.         }
  319.     }
  320.  
  321.     /* Command not found, check for macro    */
  322.  
  323.     {
  324.         char *s2;
  325.         int ret;
  326.         if ((s2 = keyspectomacro(arg)) || (s2 = menutomacro(arg))) {
  327.         s2 = (char *)strcpy(malloc(strlen(s2)+1), s2);
  328.         ret = do_command(s2);
  329.         free(s2);
  330. #if AREXX
  331.         if (ret) {
  332.             foundcmd = 1;   /* dunno about this yet for ARexx macros */
  333.             goto loop;
  334.         }
  335. #else
  336.         if (ret)
  337.             goto loop;
  338. #endif
  339.         goto fail;
  340.         }
  341.     }
  342.  
  343.     /* Command still not found, check for public macro  */
  344.     /* code to be added */
  345.  
  346. #if AREXX
  347.     do_rxImplied(arg, str);
  348. #else
  349.     title("Unknown Command");
  350. #endif
  351. fail:
  352.     --level;
  353.     while (--repi >= 0)
  354.         free(repstr[repi]);
  355.     if (aux1)
  356.         free(aux1);
  357.     return(0);
  358. loop:
  359.     if (aux1)
  360.         free(aux1);
  361.     }
  362.     --level;
  363.     while (--repi >= 0)
  364.     free(repstr[repi]);
  365.     return(1);
  366. }
  367.  
  368. void
  369. do_null()
  370. {
  371. }
  372.  
  373. void
  374. do_source()
  375. {
  376.     char buf[256];
  377.     FILE *fi;
  378.     char *str;
  379.     BPTR oldlock = CurrentDir(DupLock((BPTR)Ep->dirlock));
  380.  
  381.     if (fi = fopen(av[1], "r")) {
  382.     while (fgets(buf, 256, fi)) {
  383.         if (buf[0] == '#')
  384.         continue;
  385.         for (str = buf; *str; ++str) {
  386.         if (*str == 9)
  387.             *str = ' ';
  388.         }
  389.         if (str > buf && str[-1] == '\n')
  390.         str[-1] = 0;
  391.         do_command(buf);
  392.     }
  393.     fclose(fi);
  394.     } else {
  395.     if (av[0])
  396.         title("File not found");
  397.     }
  398.     UnLock(CurrentDir(oldlock));
  399. }
  400.  
  401.  
  402. void
  403. do_quit()
  404. {
  405.     extern char Quitflag;
  406.  
  407.     Quitflag = 1;
  408. }
  409.  
  410. void
  411. do_execute()
  412. {
  413.     BPTR oldlock = CurrentDir((BPTR)Ep->dirlock);
  414.  
  415.     system13(av[1]);
  416.     CurrentDir(oldlock);
  417. }
  418.  
  419. /*
  420.  * repeat X command
  421.  *
  422.  * Since repeat takes up 512+ stack, it should not be nested more than
  423.  * twice.
  424.  *
  425.  * (if X is not a number it can be abbr. with 2 chars)
  426.  *
  427.  * X =    N     -number of repeats
  428.  *    line  -current line # (lines begin at 1)
  429.  *    lbot  -#lines to the bottom, inc. current
  430.  *    cleft -column # (columns begin at 0)
  431.  *        (thus is also chars to the left)
  432.  *    cright-#chars to eol, including current char
  433.  *    tr    -#char positions to get to next tab stop
  434.  *    tl    -#char positions to get to next backtab stop
  435.  */
  436.  
  437. #define SC(a,b) ((a)<<8|(b))
  438.  
  439. void
  440. do_repeat()
  441. {
  442.     ubyte *ptr = av[1];
  443.     unsigned long n;
  444.     char buf1[256];
  445.     char buf2[256];
  446.  
  447.     breakreset();
  448.     strcpy(buf1, av[2]);
  449.     switch((ptr[0]<<8)+ptr[1]) {
  450.     case SC('l','i'):
  451.     n = text_lineno();
  452.     break;
  453.     case SC('l','b'):
  454.     n = text_lines() - text_lineno() + 1;
  455.     break;
  456.     case SC('c','l'):
  457.     n = text_colno();
  458.     break;
  459.     case SC('c','r'):
  460.     n = text_cols() - text_colno();
  461.     break;
  462.     case SC('t','r'):
  463.     n = text_tabsize()-(text_colno() % text_tabsize());
  464.     break;
  465.     case SC('t','l'):
  466.     n = text_colno() % text_tabsize();
  467.     if (n == 0)
  468.         n = text_tabsize();
  469.     break;
  470.     default:
  471.     n = atoi(av[1]);
  472.     break;
  473.     }
  474.     while (n > 0) {
  475.     strcpy(buf2, buf1);
  476.     if (do_command(buf2) == 0 || breakcheck()) {
  477.         Abortcommand = 1;
  478.         break;
  479.     }
  480.     --n;
  481.     }
  482. }
  483.  
  484. /*
  485.  *  BREAKOUT()
  486.  *
  487.  *  Break out the next argument.  The argument is space delimited and
  488.  *  might be quoted with `' or (), or single quoted as 'c or )c
  489.  *
  490.  *  Also:    $var        -variable insertion
  491.  *        ^c        -control character
  492.  */
  493.  
  494. char *
  495. breakout(ptr, quoted, paux)
  496. char **ptr;
  497. char **paux;
  498. char *quoted;
  499. {
  500.     char *str = *ptr;
  501.     char *base;
  502.     short count;
  503.     char opc;
  504.     char clc;
  505.     char immode;
  506.     char isaux;
  507.     char buf[256];
  508.     short di;
  509.  
  510.     {
  511.     short z = 0;
  512.  
  513.     count = z;
  514.     opc   = z;
  515.     clc   = z;
  516.     immode= z;
  517.     isaux = z;
  518.     di    = z;
  519.     }
  520.  
  521.     *quoted = 0;
  522.     *paux = NULL;
  523.     while (*str == ' ')
  524.     ++str;
  525.     if (!*str)
  526.     return(NULL);
  527.  
  528.     *ptr = str;
  529.     base = str;
  530.     while (*str) {
  531.     if (immode) {
  532.         if (di != sizeof(buf)-1)
  533.         buf[di++] = *str;
  534.         ++str;
  535.         continue;
  536.     }
  537.     if (count == 0) {
  538.         if (*str == ' ')
  539.         break;
  540.         if (*str == '\'' || *str == ')')
  541.         clc = *str;
  542.         if (*str == '`') {
  543.         opc = '`';
  544.         clc = '\'';
  545.         }
  546.         if (*str == '(') {
  547.         opc = '(';
  548.         clc = ')';
  549.         }
  550.     }
  551.     if (*str == opc) {
  552.         ++count;
  553.         if (str == *ptr) {
  554.         *quoted = 1;
  555.         base = ++str;
  556.         continue;
  557.         }
  558.     }
  559.     if (*str == clc) {
  560.         --count;
  561.         if (count == 0 && *quoted)       /*  end of argument       */
  562.         break;
  563.         if (str == *ptr && count < 0) {
  564.         immode = 1;
  565.         *quoted = 1;
  566.         base = ++str;
  567.         continue;
  568.         }
  569.     }
  570.  
  571.     /*
  572.      *  $varname $(varname) $`varname'.  I.E. three forms are allowed,
  573.      *  which allows one to insert the string almost anywhere.  The
  574.      *  first form names are limited to alpha-numerics, '-', and '_'.
  575.      */
  576.  
  577.     if (*str == '$') {
  578.         char *p2;
  579.         char *tmpptr;
  580.         char c, ce;
  581.         short len;
  582.  
  583.         ce = 0;                /*    first form  */
  584.         ++str;                /*    skip $        */
  585.         if (*str == '(') {              /*  second form */
  586.         ce = ')';
  587.         ++str;
  588.         } else if (*str == '`') {       /*  third form  */
  589.         ce = '\'';
  590.         ++str;
  591.         }
  592.         p2 = str;               /*  start of varname    */
  593.         if (ce) {                /*    until end char OR   */
  594.         while (*p2 && *p2 != ce)
  595.             ++p2;
  596.         } else {                /*    smart end-varname   */
  597.         while ((*p2 >= 'a' && *p2 <= 'z') ||
  598.             (*p2 >= 'A' && *p2 <= 'Z') ||
  599.             (*p2 >= '0' && *p2 <= '9') ||
  600.             *p2 == '-' || *p2 == '_' ) {
  601.             ++p2;
  602.         }
  603.         }
  604.         len = p2 - str;           /*  length of variable  */
  605.  
  606.         c = *p2; *p2 = 0;          /*  temp. terminate \0  */
  607.         if (strcmp(str, "scanf") == 0) {
  608.         *p2 = c;
  609.         isaux = 1;
  610.         if (di + strlen(String) < sizeof(buf)-1) {
  611.             strcpy(buf + di, String);
  612.             di += strlen(buf + di);
  613.         }
  614.         str += len;            /*    next string pos     */
  615.         if (ce)
  616.             ++str;
  617.         continue;
  618.         }
  619.         if (strcmp(str, "fpath") == 0) {
  620.         short i;
  621.         for (i = strlen(Ep->Name); i >= 0; --i) {
  622.             if (Ep->Name[i] == ':' || Ep->Name[i] == '/')
  623.             break;
  624.         }
  625.         ++i;
  626.         *p2 = c;
  627.         isaux = 1;
  628.         if (di + i < sizeof(buf)-1) {
  629.             movmem(Ep->Name, buf + di, i);
  630.             di += i;
  631.             buf[di] = 0;
  632.         }
  633.         str += len;
  634.         if (ce)
  635.             ++str;
  636.         continue;
  637.         }
  638.         if (strcmp(str, "fname") == 0) {
  639.         short i;
  640.         short j;
  641.         for (i = strlen(Ep->Name); i >= 0; --i) {
  642.             if (Ep->Name[i] == ':' || Ep->Name[i] == '/')
  643.             break;
  644.         }
  645.         ++i;
  646.         j = strlen(Ep->Name + i);
  647.         *p2 = c;
  648.         isaux = 1;
  649.         if (di + j < sizeof(buf)-1) {
  650.             movmem(Ep->Name + i, buf + di, j);
  651.             di += j;
  652.             buf[di] = 0;
  653.         }
  654.         str += len;
  655.         if (ce)
  656.             ++str;
  657.         continue;
  658.         }
  659.         if (strcmp(str, "filename") == 0) {
  660.         *p2 = c;
  661.         isaux = 1;
  662.         if (di + strlen(Ep->Name) < sizeof(buf)-1) {
  663.             strcpy(buf + di, Ep->Name);
  664.             di += strlen(buf + di);
  665.         }
  666.         str += len;
  667.         if (ce)
  668.             ++str;
  669.         continue;
  670.         }
  671.         if (strcmp(str, "colno") == 0) {
  672.         *p2 = c;
  673.         isaux = 1;
  674.         if (di < sizeof(buf)-8) {
  675.             sprintf(buf + di, "%ld", Ep->Column + 1);
  676.             di += strlen(buf + di);
  677.         }
  678.         str += len;
  679.         if (ce)
  680.             ++str;
  681.         continue;
  682.         }
  683.         if (strcmp(str, "lineno") == 0) {
  684.         *p2 = c;
  685.         isaux = 1;
  686.         if (di < sizeof(buf)-8) {
  687.             sprintf(buf + di, "%ld", Ep->Line + 1);
  688.             di += strlen(buf + di);
  689.         }
  690.         str += len;
  691.         if (ce)
  692.             ++str;
  693.         continue;
  694.         }
  695.         if (strcmp(str, "margin") == 0) {                       /* MMW */
  696.         *p2 = c;
  697.         isaux = 1;
  698.         if (di < sizeof(buf)-8) {
  699.             sprintf(buf + di, "%ld", Ep->Margin);
  700.             di += strlen(buf + di);
  701.         }
  702.         str += len;
  703.         if (ce)
  704.             ++str;
  705.         continue;
  706.         }
  707.         if (strcmp(str, "modified") == 0) {                       /* MMW */
  708.         *p2 = c;
  709.         isaux = 1;
  710.         if (di < sizeof(buf)-8) {
  711.             sprintf(buf + di, "%ld", Ep->Modified ? 1 : 0);
  712.             di += strlen(buf + di);
  713.         }
  714.         str += len;
  715.         if (ce)
  716.             ++str;
  717.         continue;
  718.         }
  719.         if (strcmp(str, "currentline") == 0) {
  720.         short i;
  721.  
  722.         *p2 = c;
  723.         isaux = 1;
  724.         if (di < sizeof(buf)-8) {
  725.             for (i = strlen(Current) - 1; i >= 0 && Current[i] == ' '; --i);
  726.             ++i;
  727.             if (i > 0)
  728.             strncpy(buf + di, Current, i);
  729.             *(buf + di + i) = 0;
  730.             di += strlen(buf + di);
  731.         }
  732.         str += len;
  733.         if (ce)
  734.             ++str;
  735.         continue;
  736.         }
  737.  
  738.  
  739.  
  740.  
  741.         if (tmpptr = getvar(str)) {
  742.         p2 = tmpptr;
  743.         str[len] = c;
  744.         isaux = 1;
  745.         if (di + strlen(p2) < sizeof(buf)-1) {
  746.             strcpy(buf + di, p2);
  747.             di += strlen(buf + di);
  748.         }
  749.         str += len;
  750.         if (ce)
  751.             ++str;
  752.         free(p2);
  753.         continue;
  754.         }
  755.         *p2 = c;
  756.         --str;
  757.         if (ce)
  758.         --str;
  759.     }
  760.     if (*str == '^' && (str[1] & 0x1F)) {
  761.         ++str;
  762.         *str &= 0x1F;
  763.         isaux = 1;
  764.     }
  765.     if (*str == '\\' && str[1]) {
  766.         ++str;
  767.         isaux = 1;
  768.     }
  769.     buf[di++] = *str++;
  770.     }
  771.     buf[di++] = 0;
  772.     if (isaux) {
  773.     *paux = malloc(di);
  774.     strcpy(*paux, buf);
  775.     base = *paux;
  776.     }
  777.     if (*str) {         /*    space ended */
  778.     *str = '\0';
  779.     *ptr = str + 1;     /*    next arg    */
  780.     } else {
  781.     *ptr = str;        /*    last arg    */
  782.     }
  783.     return(base);
  784. }
  785.  
  786.  
  787.